'\" te
.\" Copyright (c) 2003, Sun Microsystems, Inc. All Rights Reserved.
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License").  You may not use this file except in compliance with the License.
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.  See the License for the specific language governing permissions and limitations under the License.
.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE.  If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
.TH RCMSCRIPT 5 "Feb 18, 2003"
.SH NAME
rcmscript \- script interface specification for the Reconfiguration and
Coordination Manager
.SH SYNOPSIS
.LP
.nf
\fB\fIrcm_scriptname\fR scriptinfo\fR
.fi

.LP
.nf
\fB\fIrcm_scriptname\fR register\fR
.fi

.LP
.nf
\fB\fIrcm_scriptname\fR resourceinfo \fIresourcename\fR\fR
.fi

.LP
.nf
\fB\fIrcm_scriptname\fR queryremove \fIresourcename\fR\fR
.fi

.LP
.nf
\fB\fIrcm_scriptname\fR preremove \fIresourcename\fR\fR
.fi

.LP
.nf
\fB\fIrcm_scriptname\fR postremove \fIresourcename\fR\fR
.fi

.LP
.nf
\fB\fIrcm_scriptname\fR undoremove \fIresourcename\fR\fR
.fi

.SH DESCRIPTION
.LP
Reconfiguration and Coordination Manager (RCM) is a framework designed to
coordinate device consumers during Solaris Dynamic Reconfiguration (DR). The
interfaces specified in this man page allow device consumers, such as
application vendors or site administrators, to act before and after DR
operations take place by providing RCM scripts. You can write your own RCM
scripts to shut down your applications, or to cleanly release the devices from
your applications during dynamic remove operations.
.sp
.LP
An RCM script is an executable perl script, a shell script or a binary. Perl is
the recommended language. Each script is run in its own address space using the
user-id of the script file owner.
.sp
.LP
An RCM script is invoked on demand in response to DR as follows:
.sp
.in +2
.nf
\fI<scriptname>\fR \fI<command>\fR [\fIargs\fR ...]
.fi
.in -2
.sp

.sp
.LP
Every script must implement the following RCM commands:
.sp
.ne 2
.na
\fB\fBscriptinfo\fR\fR
.ad
.RS 16n
Get script information.
.RE

.sp
.ne 2
.na
\fB\fBregister\fR\fR
.ad
.RS 16n
Register devices the script handles.
.RE

.sp
.ne 2
.na
\fB\fBresourceinfo\fR\fR
.ad
.RS 16n
Get resource information.
.RE

.sp
.LP
A script might include some or all the of the following commands:
.sp
.ne 2
.na
\fB\fBqueryremove\fR\fR
.ad
.RS 15n
Queries whether the resource can be released.
.RE

.sp
.ne 2
.na
\fB\fBpreremove\fR\fR
.ad
.RS 15n
Releases the resource.
.RE

.sp
.ne 2
.na
\fB\fBpostremove\fR\fR
.ad
.RS 15n
Provides post-resource removal notification.
.RE

.sp
.ne 2
.na
\fB\fBundoremove\fR\fR
.ad
.RS 15n
Undo the actions done in preremove.
.RE

.sp
.LP
When a script's \fBregister\fR command is run, the script should supply, in
return data, all resource names the script or its application handles that
could potentially be removed by DR. A resource name refers to a name in
\fB/dev\fR path name.
.sp
.LP
Below is a high-level overview of the sequence of script invocations that
occurs when dynamic removal of a script's registered resource is attempted. See
the COMMANDS section for a detailed description of the commands.
.RS +4
.TP
1.
Prior to removing the resource from the system during DR, the script's
\fBqueryremove\fR command is run:
.sp
.in +2
.nf
\fI<scriptname>\fR queryremove \fI<resourcename>\fR
.fi
.in -2
.sp

The script should check for obvious reasons why the resource can not be removed
from the perspective of its service or application.
.RE
.RS +4
.TP
2.
If the script indicates that the resource can be removed in the
\fBqueryremove\fR command. The script's \fBpreremove\fR command is run:
.sp
.in +2
.nf
\fI<scriptname>\fR preremove \fI<resourcename>\fR
.fi
.in -2
.sp

The script releases the resource from the service or application represented by
the script and prepares for the resource removal. Releasing the resource
includes closing the resource if the resource is currently opened by its
application.
.RE
.RS +4
.TP
3.
The system then proceeds to remove the resource.
.RE
.RS +4
.TP
4.
If the system has removed the resource successfully the script's
\fBpostremove\fR command is run:
.sp
.in +2
.nf
\fI<scriptname>\fR postremove \fI<resourcename>\fR
.fi
.in -2
.sp

Otherwise the script's \fBundoremove\fR command is run:
.sp
.in +2
.nf
\fI<scriptname>\fR undoremove \fI<resourcename>\fR
.fi
.in -2
.sp

.RE
.sp
.LP
For any commands the script does not implement, it must exit with exit status
of 2. RCM silently returns success for the script's unimplemented commands.
.sp
.LP
A script performs the following basic steps:
.RS +4
.TP
.ie t \(bu
.el o
Takes RCM command and additional arguments from the command line and
environment parameters.
.RE
.RS +4
.TP
.ie t \(bu
.el o
Processes the command.
.RE
.RS +4
.TP
.ie t \(bu
.el o
Writes the expected return data to stdout as \fIname=value\fR pairs delimited
by newlines, where \fIname\fR is the name of the return data item that RCM
expects and \fIvalue\fR is the value associated with the data item.
.RE
.SS "Environment"
.LP
The initial environment of RCM scripts is set as follows:
.RS +4
.TP
.ie t \(bu
.el o
Process UID is set to the UID of the script.
.RE
.RS +4
.TP
.ie t \(bu
.el o
Process GID is set to the GID of the script.
.RE
.RS +4
.TP
.ie t \(bu
.el o
\fBPATH\fR variable is set to \fB/usr/sbin:/usr/bin\fR.
.RE
.RS +4
.TP
.ie t \(bu
.el o
Current working directory is set to:
.RS +4
.TP
.ie t \(bu
.el o
\fB/var/run\fR for scripts owned by root
.RE
.RS +4
.TP
.ie t \(bu
.el o
\fB/tmp\fR for scripts not owned by root
.RE
.RE
.RS +4
.TP
.ie t \(bu
.el o
File descriptor 0 (stdin) is set to \fB/dev/null\fR
.RE
.RS +4
.TP
.ie t \(bu
.el o
Environment variable \fBRCM_ENV_DEBUG_LEVEL\fR is set to the debug level.
Logging is discussed below.
.RE
.RS +4
.TP
.ie t \(bu
.el o
 The following environment variables are also set where possible:
.RS +4
.TP
.ie t \(bu
.el o
\fBLANG\fR
.RE
.RS +4
.TP
.ie t \(bu
.el o
\fBLC_COLLATE\fR
.RE
.RS +4
.TP
.ie t \(bu
.el o
\fBLC_CTYPE\fR
.RE
.RS +4
.TP
.ie t \(bu
.el o
\fBLC_MESSAGES\fR
.RE
.RS +4
.TP
.ie t \(bu
.el o
\fBLC_MONETARY\fR
.RE
.RS +4
.TP
.ie t \(bu
.el o
\fBLC_NUMERIC\fR
.RE
.RS +4
.TP
.ie t \(bu
.el o
\fBLC_TIME\fR
.RE
.RS +4
.TP
.ie t \(bu
.el o
\fBLC_ALL\fR
.RE
.RS +4
.TP
.ie t \(bu
.el o
\fBTZ\fR
.RE
See \fBenviron\fR(7) for a description of these variables. See \fBgettext\fR(1)
for details on retrieving localized messages.
.RE
.sp
.LP
All environment variable names beginning with \fBRCM_ENV_\fR are reserved for
use by the RCM.
.sp
.LP
The character encoding used by the RCM and RCM scripts to exchange RCM
commands, environment parameters, and name-value pairs is ASCII unless the
controlling environment variables are specified otherwise.
.SS "Commands"
.SS "\fBscriptinfo\fR"
.LP
The \fBscriptinfo\fR command is invoked to gather information about the script.
.sp
.ne 2
.na
\fBReturn data:\fR
.ad
.RS 16n
If successful, the script must write the following name-value pairs to stdout
and exit with status 0:
.RS +4
.TP
.ie t \(bu
.el o
\fBrcm_script_version=1\fR
.RE
.RS +4
.TP
.ie t \(bu
.el o
\fBrcm_script_func_info=\fR\fIscript_func_info\fR
.RE
.RS +4
.TP
.ie t \(bu
.el o
\fBrcm_cmd_timeout=\fR\fIcommand_timeout_value\fR
.RE
where \fIscript_func_info\fR is a localized human-readable message describing
the functionality of the script.
.sp
The RCM monitors the execution time of RCM commands by RCM scripts.
\fIcommand_timeout_value\fR is the maximum time in seconds the script is
expected to take to process any RCM command except the \fBscriptinfo\fR command
itself. If an RCM script does not process the RCM command and exit within this
time, RCM sends a \fBSIGABRT\fR signal to the script process. RCM then waits
for a few seconds for the script to finish the processing of the current RCM
command and exit. If the script does not exit within this time, RCM sends a
\fBSIGKILL\fR signal to the script.
.sp
The \fBrcm_cmd_timeout\fR name-value pair is optional. It is only needed if the
script is expected to take more than a few seconds to process any RCM command.
Setting this name to a value of 0 (zero) disables the timer. If this name-value
pair is not supplied, a default value is assigned by the RCM.
.sp
Upon failure, the script must specify the failure reason using the name-value
pair \fBrcm_failure_reason\fR and exit with status 1.
.RE

.SS "\fBregister\fR"
.LP
The \fBregister\fR command is invoked to allow a script to specify the
resources that it or its application handles that could potentially be removed
by DR. The script has to supply all its resource names to RCM using the
name-value pair \fBrcm_resource_name\fR.
.sp
.ne 2
.na
\fBReturn Data:\fR
.ad
.RS 16n
If successful, the script must write the following name-value pairs to stdout
and exit with status 0:
.sp
.in +2
.nf
rcm_resource_name=\fIresourcename\fR
rcm_resource_name=\fIresourcename\fR
           .
           .
           .
.fi
.in -2
.sp

where \fIresourcename\fR is the name of the resource the script is interested
in.
.sp
Upon failure, the script must specify the failure reason using the name-value
pair \fBrcm_failure_reason\fR and exit with status 1.
.RE

.SS "\fBresourceinfo\fR \fIresourcename\fR"
.LP
The \fBresourceinfo\fR command is invoked to get the usage information about
\fIresourcename\fR.
.sp
.ne 2
.na
\fBReturn Data:\fR
.ad
.RS 16n
If successful, the script must write the following name-value pair to stdout
and exit with status 0:
.sp
.in +2
.nf
rcm_resource_usage_info=\fIresource_usage\fR
.fi
.in -2
.sp

where \fIresource_usage\fR is a localized human readable message describing the
usage of the resource by the script.
.sp
Upon failure, the script must specify the failure reason using the name-value
pair \fBrcm_failure_reason\fR and exit with status 1.
.RE

.SS "\fBqueryremove\fR \fIresourcename\fR"
.LP
Prior to removing the resource from the system, the \fBqueryremove\fR command
is invoked to query the script to determine whether the script can release the
given resource successfully from the service or application it represents. The
script does not actually release the resource. The script might indicate that
it is not able to release the resource if the resource is critical for its
service or application.
.sp
.LP
Additional environment parameter:
.sp
.ne 2
.na
\fB\fBRCM_ENV_FORCE\fR\fR
.ad
.RS 17n
Can be one of:
.sp
.ne 2
.na
\fB\fBFALSE\fR\fR
.ad
.RS 9n
Normal request.
.RE

.sp
.ne 2
.na
\fB\fBTRUE\fR\fR
.ad
.RS 9n
Request is urgent. The script should check whether the resource can be released
successfully by force, such as by using the force option to unmount a file
system.
.RE

.RE

.sp
.ne 2
.na
\fBReturn Data:\fR
.ad
.RS 16n
If the command succeeds, the script must return no data and exit with status 0.
.sp
If the script would not be able to release the resource, it must specify the
reason using the name-value pair \fBrcm_failure_reason\fR and exit with status
3.
.sp
Upon any other failure, the script must specify the failure reason using the
name-value pair \fBrcm_failure_reason\fR and exit with status 1.
.RE

.SS "\fBpreremove\fR \fIresourcename\fR"
.LP
The \fBpreremove\fR command is invoked prior to an attempt to remove the given
\fIresourcename\fR. In response to this command the script can either release
the resource (including closing the device if the device is currently opened)
from the service or application it represents or indicate that it can not
release the resource if the resource is critical for its service or
application.
.sp
.LP
Additional environment parameter:
.sp
.ne 2
.na
\fB\fBRCM_ENV_FORCE\fR\fR
.ad
.RS 17n
Can be one of:
.sp
.ne 2
.na
\fB\fBFALSE\fR\fR
.ad
.RS 9n
Normal request.
.RE

.sp
.ne 2
.na
\fB\fBTRUE\fR\fR
.ad
.RS 9n
Request is urgent. The script should make extra effort to release the resource,
such as by using the force option to unmount a file system.
.RE

.RE

.sp
.ne 2
.na
\fBReturn Data:\fR
.ad
.RS 16n
If the command succeeds, the script must return no data and exit with status 0.
.sp
If the script cannot release the resource, it must specify the reason using the
name-value pair \fBrcm_failure_reason\fR and exit with status 3.
.sp
Upon any other failure, the script must specify the failure reason using the
name-value pair \fBrcm_failure_reason\fR and exit with status 1.
.RE

.SS "\fBpostremove\fR \fIresourcename\fR"
.LP
The \fBpostremove\fR command is invoked after the given \fIresourcename\fR has
been removed.
.sp
.ne 2
.na
\fBReturn Data:\fR
.ad
.RS 16n
If the command succeeds, the script must return no data and exit with status 0.
.sp
Upon failure, the script must specify the failure reason using the name-value
pair \fBrcm_failure_reason\fR and exit with status 1.
.RE

.sp
.LP
\fBundoremove\fR \fIresourcename\fR
.sp
.LP
The \fBundoremove\fR command is invoked to undo what was done in the previous
\fBpreremove\fR command for the given \fIresourcename\fR. The script can bring
the state of the resource to the same state it was in when the script received
the \fBpreremove\fR command for that resource.
.sp
.ne 2
.na
\fBReturn Data:\fR
.ad
.RS 16n
If the command succeeds, the script must return no data and exit with status 0.
.sp
Upon failure, the script must specify the failure reason using the name-value
pair \fBrcm_failure_reason\fR and exit with status 1.
.RE

.SS "Logging"
.LP
A script must log all error and debug messages by writing to stdout the
name-value pairs listed below. The logged messages go to \fBsyslogd\fR(8) with
the \fBsyslog\fR facility of \fBLOG_DAEMON\fR. See \fBsyslog.conf\fR(5).
.sp
.ne 2
.na
\fB\fBrcm_log_err=\fR\fImessage\fR\fR
.ad
.RS 25n
Logs the \fImessage\fR with the syslog level of \fBLOG_ERR\fR.
.RE

.sp
.ne 2
.na
\fB\fBrcm_log_warn=\fR\fImessage\fR\fR
.ad
.RS 25n
Logs the \fImessage\fR with the syslog level of \fBLOG_WARNING\fR.
.RE

.sp
.ne 2
.na
\fB\fBrcm_log_info=\fR\fImessage\fR\fR
.ad
.RS 25n
Logs the \fImessage\fR with the syslog level of \fBLOG_INFO\fR.
.RE

.sp
.ne 2
.na
\fB\fBrcm_log_debug=\fR\fImessage\fR\fR
.ad
.RS 25n
Logs the \fImessage\fR with the syslog level of \fBLOG_DEBUG\fR.
.RE

.sp
.LP
A script can use the environment variable \fBRCM_ENV_DEBUG_LEVEL\fR to control
the amount of information to log. \fBRCM_ENV_DEBUG_LEVEL\fR is a numeric value
ranging from 0 to 9, with 0 meaning log the least amount of information and 9
meaning log the most.
.SS "Installing or Removing RCM Scripts"
.LP
You must use the following format to name a script:
.sp
.in +2
.nf
\fIvendor\fR,\fIservice\fR
.fi
.in -2
.sp

.sp
.LP
where \fIvendor\fR is the stock symbol (or any distinctive name) of the vendor
providing the script and \fIservice\fR is the name of service the script
represents.
.sp
.LP
You must be a superuser (root) to install or remove an RCM script.
.sp
.LP
Select one of the following directories where you want to place the script:
.sp
.ne 2
.na
\fB\fB/etc/rcm/scripts\fR\fR
.ad
.sp .6
.RS 4n
Scripts for specific systems
.RE

.sp
.ne 2
.na
\fB\fB/usr/platform/`uname -i`/lib/rcm/scripts\fR\fR
.ad
.sp .6
.RS 4n
Scripts for specific hardware implementation
.RE

.sp
.ne 2
.na
\fB\fB/usr/platform/`uname -m`/lib/rcm/scripts\fR\fR
.ad
.sp .6
.RS 4n
Scripts for specific hardware class
.RE

.sp
.ne 2
.na
\fB\fB/usr/lib/rcm/scripts\fR\fR
.ad
.sp .6
.RS 4n
Scripts for any hardware
.RE

.SS "Installing a Script"
.LP
To install a script, copy the script to the appropriate directory from the list
above, change the userid and the groupid of the script to the desired values,
and send \fBSIGHUP\fR to \fBrcm_daemon\fR. For example:
.sp
.in +2
.nf
# cp SUNW,sample.pl /usr/lib/rcm/scripts
# chown user[:group] /usr/lib/rcm/scripts/SUNW,sample.pl
# pkill -HUP -x -u root rcm_daemon
.fi
.in -2
.sp

.SS "Removing a script"
.LP
Remove the script from the appropriate directory from the list above and send
\fBSIGHUP\fR to \fBrcm_daemon\fR. For example:
.sp
.in +2
.nf
# rm /usr/lib/rcm/scripts/SUNW,sample.pl
# pkill -HUP -x -u root rcm_daemon
.fi
.in -2
.sp

.SH EXAMPLES
.LP
\fBExample 1 \fRSite Customization RCM Script
.sp
.in +2
.nf
#! /usr/bin/perl -w

#
# A sample site customization RCM script for a tape backup application.
#
# This script registers all tape drives in the system with RCM.
# When the system attempts to remove a tape drive by DR the script
# does the following:
#   - if the tape drive is not being used for backup, it allows the
#     DR to continue.
#   - if the tape drive is being used for backup, and when DR is not
#     forced (RCM_ENV_FORCE=FALSE) it indicates that it cannot release
#     the tape drive with appropriate error message. When forced
#     (RCM_ENV_FORCE=TRUE) it kills the tape backup application in
#     order to allow the DR to continue.
#
# This script does not implement the postremove and undoremove commands
# since there is nothing to cleanup after DR remove operation is
# completed or failed. If any cleanup is needed after the DR removal
# completed, postremove command needs to implemented. If any cleanup is
# needed in the event of DR removal failure, undoremove command needs
# to be implemented.
#

use strict;

my ($cmd, %dispatch);

$cmd = shift(@ARGV);

# dispatch table for RCM commands
%dispatch = (
    "scriptinfo"    =>      \&do_scriptinfo,
    "register"      =>      \&do_register,
    "resourceinfo"  =>      \&do_resourceinfo,
    "queryremove"   =>      \&do_preremove,
    "preremove"     =>      \&do_preremove
);

if (defined($dispatch{$cmd})) {
    &{$dispatch{$cmd}};
} else {
    exit (2);
}

sub do_scriptinfo
{
    print "rcm_script_version=1\en";
    print "rcm_script_func_info=Tape backup appl script for DR\en";
    exit (0);
}

sub do_register
{
    my ($dir, $f, $errmsg);

    $dir = opendir(RMT, "/dev/rmt");
    if (!$dir) {
        $errmsg = "Unable to open /dev/rmt directory: $!";
        print "rcm_failure_reason=$errmsg\en";
        exit (1);
    }

    while ($f = readdir(RMT)) {
        # ignore hidden files and multiple names for the same device
        if (($f !~ /^\./) && ($f =~ /^[0-9]+$/)) {
            print "rcm_resource_name=/dev/rmt/$f\en";
        }

    }

    closedir(RMT);
    exit (0);
}

sub do_resourceinfo
{
    my ($rsrc, $unit);

    $rsrc = shift(@ARGV);
    if ($rsrc =~ /^\e/dev\e/rmt\e/([0-9]+)$/) {
        $unit = $1;
        print "rcm_resource_usage_info=Backup Tape Unit Number $unit\en";
        exit (0);
    } else {
        print "rcm_failure_reason=Unknown tape device!\en";
        exit (1);
    }
}

sub do_preremove
{
    my ($rsrc);

    $rsrc = shift(@ARGV);

    # check if backup application is using this resource
    # if (the backup application is not running on $rsrc) {
    # allow the DR to continue
    #        exit (0);
    #}
    #
    # If RCM_ENV_FORCE is FALSE deny the operation.
    # If RCM_ENV_FORCE is TRUE kill the backup application in order
    # to allow the DR operation to proceed
    #
    if ($ENV{RCM_ENV_FORCE} eq 'TRUE') {
        if ($cmd eq 'preremove') {
            # kill the tape backup application
        }
        exit (0);
    } else {
        #
        # indicate that the tape drive can not be released
        # since the device is being used for backup by the
        # tape backup application
        #
        print "rcm_failure_reason=tape backup in progress pid=...\en";
        exit (3);

    }
}
.fi
.in -2

.SH EXIT STATUS
.LP
A script must exit with following exit status values:
.sp
.ne 2
.na
\fB\fB0\fR\fR
.ad
.RS 5n
Operation specified by the given RCM command has been executed successfully by
the script. For \fBqueryremove\fR command it also means that the script can
successfully release the resource.
.RE

.sp
.ne 2
.na
\fB\fB1\fR\fR
.ad
.RS 5n
An error occurred while processing the RCM command. The script should provide
the error message to RCM using the name-value pair \fBrcm_failure_reason\fR
before exiting.
.RE

.sp
.ne 2
.na
\fB\fB2\fR\fR
.ad
.RS 5n
The script does not support the given RCM command. A script must exit with this
status if it cannot understand the given RCM command.
.RE

.sp
.ne 2
.na
\fB\fB3\fR\fR
.ad
.RS 5n
Indicates that the script cannot release the resource for \fBpreremove\fR and
\fBqueryremove\fR commands. The script should provide a message to RCM
specifying the reason for not being able to release the resource using the
name-value pair \fBrcm_failure_reason\fR before exiting.
.RE

.SH ERRORS
.LP
If a script cannot successfully process an RCM command, it must supply to the
RCM a message indicating the reason for failure by writing a name-value pair,
in the form shown below, to stdout and exiting with the appropriate exit
status.
.sp
.in +2
.nf
rcm_failure_reason=\fIfailure_reason\fR
.fi
.in -2
.sp

.sp
.LP
where \fIfailure_reason\fR is a localized human readable message describing the
reason for failure of the RCM command.
.SH ATTRIBUTES
.LP
See \fBattributes\fR(7) for descriptions of the following attributes:
.sp

.sp
.TS
box;
c | c
l | l .
ATTRIBUTE TYPE	ATTRIBUTE VALUE
_
Interface Stability	Evolving
.TE

.SH SEE ALSO
.LP
.BR gettext (1),
.BR syslog (3C),
.BR signal.h (3HEAD),
.BR syslog.conf (5),
.BR attributes (7),
.BR environ (7),
.BR cfgadm (8),
.BR cfgadm_pci (8),
.BR cfgadm_scsi (8)
.SH NOTES
.LP
RCM scripts are expected to properly handle all RCM commands that the script
implements and to log all errors. Only root has permission to add or remove an
RCM script. An ill-behaved RCM script can cause unexpected DR failures.
.sp
.LP
RCM commands are invoked only for the resources whose subsystems participate
within the RCM framework. Currently, not all subsystems participate within the
RCM framework.
